#include<iostream>
#include<string>
#include<vector>
#include<memory>
#include<set>
#include<algorithm>
using namespace std;
class Folder;
class Message;
class Message{
	friend class Folder;
public:
	explicit Message(const string &str):contents(str){}
	Message(const Message&);
	Message& operator=(const Message&);
	~Message();
	void save(Folder &);
	void remove(Folder &);
	void addFld(Folder *);
	void remFld(Folder *);
	void change_content(const string &str);
private:
	string contents;
	set<Folder*> folders;
	void add_to_Folders(const Message&);
	void remove_from_Folders();
};
class Folder{
	friend class Message;
public:
	explicit Folder(const string &str):name(str){}
	Folder(const Folder&);
	Folder& operator=(const Folder&);
	~Folder();
	void addMsg(Message *);
	void remMsg(Message *);
	void print_allMsgs();
private:
	string name;
	set<Message*> messages;
	void add_to_Messages(const Folder&);
	void remove_from_Messages();
};
void Message::save(Folder &f){
	folders.insert(&f);
	f.addMsg(this);
}
void Message::remove(Folder &f){
	folders.erase(&f);
	f.remMsg(this);
}
void Message::change_content(const string &str){
	this->contents=str;
}
void Message::add_to_Folders(const Message &m)
{
	for(auto f:m.folders){
		f->addMsg(this);
	}
}
Message::Message(const Message &m):contents(m.contents),folders(m.folders)
{
	add_to_Folders(m);
}
void Message::remove_from_Folders()
{
	for(auto f:folders)
		f->remMsg(this);
}
Message::~Message()
{
	remove_from_Folders();
}
Message& Message::operator=(const Message &rhs)
{
	remove_from_Folders();
	contents=rhs.contents;
	folders=rhs.folders;
	add_to_Folders(rhs);
	return *this;
}
void Message::addFld(Folder *f)
{
	folders.insert(f);
}
void Message::remFld(Folder *f)
{
	folders.erase(f);
}
void Folder::addMsg(Message *m)
{
	messages.insert(m);
}
void Folder::remMsg(Message *m)
{
	messages.erase(m);
}
void Folder::add_to_Messages(const Folder &f)
{
	for(auto m:f.messages)
		m->addFld(this);
}
void Folder::remove_from_Messages()
{
	for(auto m:messages)
		m->remFld(this);
}
Folder::Folder(const Folder &f):messages(f.messages)
{
	add_to_Messages(f);
}
Folder& Folder::operator=(const Folder &f)
{
	remove_from_Messages();
	messages=f.messages;
	add_to_Messages(f);
	return *this;
}
Folder::~Folder()
{
	remove_from_Messages();
}
void Folder::print_allMsgs()
{
	for(auto m:messages)
		cout<<name<<":"<<m->contents<<endl;
}
int main()
{
	Message msg1("hello1");
	Message msg2("good2");
	Message msg3("good3");
	Message msg4("good4");
	Folder fd1("fd1");
	Folder fd2("fd2");
	Folder fd3("fd3");
	msg1.save(fd1);
	msg1.save(fd2);
	msg2.save(fd3);
	msg4.save(fd1);
	msg3.save(fd1);
	msg2.save(fd2);
	msg4.save(fd2);
	msg1.save(fd3);
	Message msg5=msg1;
	fd1.print_allMsgs();
	fd2.print_allMsgs();
	fd3.print_allMsgs();
	msg1.change_content("shit");
	fd1.print_allMsgs();
	fd2.print_allMsgs();
	fd3.print_allMsgs();
	return 0;
}






